 /*******************************************************************************
  * Copyright (c) 2000, 2006 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
  * Contributors:
  * IBM Corporation - initial API and implementation
  *******************************************************************************/

 package org.eclipse.ui.texteditor;


 import java.lang.reflect.InvocationTargetException ;
 import java.util.Map ;
 import java.util.MissingResourceException ;
 import java.util.ResourceBundle ;

 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.NullProgressMonitor;

 import org.eclipse.swt.custom.BusyIndicator;
 import org.eclipse.swt.widgets.Shell;

 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
 import org.eclipse.jface.operation.IRunnableWithProgress;
 import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.IDocument;
 import org.eclipse.jface.text.IRegion;
 import org.eclipse.jface.text.IRewriteTarget;
 import org.eclipse.jface.text.TextUtilities;


 /**
  * An action to convert line delimiters of a text editor document to a
  * particular line delimiter.
  *
  * @since 2.0
  * @deprecated since 3.1. Line delimiter conversion has been modified to work on groups of files rather than being editor specific
  */
 public class ConvertLineDelimitersAction extends TextEditorAction {


     /** The target line delimiter. */
     private final String fLineDelimiter;

     /**
      * Creates a line delimiter conversion action.
      *
      * @param editor the editor
      * @param lineDelimiter the target line delimiter to convert the editor's document to
      */
     public ConvertLineDelimitersAction(ITextEditor editor, String lineDelimiter) {
         this(EditorMessages.getBundleForConstructedKeys(), "dummy", editor, lineDelimiter); //$NON-NLS-1$
 }

     /**
      * Creates a line delimiter conversion action.
      *
      * @param bundle the resource bundle
      * @param prefix the prefix for the resource bundle lookup
      * @param editor the editor
      * @param lineDelimiter the target line delimiter to convert the editor's document to
      */
     public ConvertLineDelimitersAction(ResourceBundle bundle, String prefix, ITextEditor editor, String lineDelimiter) {
         super(bundle, prefix, editor);
         fLineDelimiter= lineDelimiter;

         String platformLineDelimiter= System.getProperty("line.separator"); //$NON-NLS-1$
 setText(getString(getLabelKey(fLineDelimiter, platformLineDelimiter)));

         update();
     }

     /*
      * @see org.eclipse.jface.action.Action#run()
      */
     public void run() {

         try {

             ITextEditor editor= getTextEditor();
             if (editor == null)
                 return;

             if (!validateEditorInputState())
                 return;

             Object adapter= editor.getAdapter(IRewriteTarget.class);
             if (adapter instanceof IRewriteTarget) {

                 IRewriteTarget target= (IRewriteTarget) adapter;
                 IDocument document= target.getDocument();
                 if (document != null) {
                     Shell shell= getTextEditor().getSite().getShell();
                     ConvertRunnable runnable= new ConvertRunnable(target, fLineDelimiter);

                     if (document.getNumberOfLines() < 40) {
                         BusyIndicator.showWhile(shell.getDisplay(), runnable);

                     } else {
                         ProgressMonitorDialog dialog= new ProgressMonitorDialog(shell);
                         dialog.run(false, true, runnable);
                     }
                 }
             }

         } catch (InterruptedException e) {
             // action canceled
 } catch (InvocationTargetException e) {
             // should not happen
 }
     }

     /**
      * A runnable that converts all line delimiters of a document to <code>lineDelimiter</code>.
      */
     private static class ConvertRunnable implements IRunnableWithProgress, Runnable {

         /** The rewrite target */
         private final IRewriteTarget fRewriteTarget;
         /** The line delimiter to which to convert to */
         private final String fLineDelimiter;

         /**
          * Returns a new runnable for converting all line delimiters in
          * the <code>rewriteTarget</code> to <code>lineDelimter</code>.
          * @param rewriteTarget
          * @param lineDelimiter
          */
         public ConvertRunnable(IRewriteTarget rewriteTarget, String lineDelimiter) {
             fRewriteTarget= rewriteTarget;
             fLineDelimiter= lineDelimiter;
         }

         /*
          * @see IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor)
          */
         public void run(IProgressMonitor monitor) throws InvocationTargetException , InterruptedException {

             IDocument document= fRewriteTarget.getDocument();
             final int lineCount= document.getNumberOfLines();
             monitor.beginTask(EditorMessages.Editor_ConvertLineDelimiter_title, lineCount);

             final boolean isLargeUpdate= lineCount > 50;
             if (isLargeUpdate)
                 fRewriteTarget.setRedraw(false);
             fRewriteTarget.beginCompoundChange();

             Map partitioners= TextUtilities.removeDocumentPartitioners(document);

             try {
                 for (int i= 0; i < lineCount; i++) {
                     if (monitor.isCanceled())
                         throw new InterruptedException ();

                     final String delimiter= document.getLineDelimiter(i);
                     if (delimiter != null && delimiter.length() > 0 && !delimiter.equals(fLineDelimiter)) {
                         IRegion region= document.getLineInformation(i);
                         document.replace(region.getOffset() + region.getLength(), delimiter.length(), fLineDelimiter);
                     }

                     monitor.worked(1);
                 }

             } catch (BadLocationException e) {
                 throw new InvocationTargetException (e);

             } finally {

                 if (partitioners != null)
                     TextUtilities.addDocumentPartitioners(document, partitioners);

                 fRewriteTarget.endCompoundChange();
                 if (isLargeUpdate)
                     fRewriteTarget.setRedraw(true);

                 monitor.done();
             }
         }

         /*
          * @see Runnable#run()
          */
         public void run() {
             try {
                 run(new NullProgressMonitor());

             } catch (InterruptedException e) {
                 // should not happen

             } catch (InvocationTargetException e) {
                 // should not happen
 }
         }
     }

 // /**
 // * Returns whether the given document uses only the given line delimiter.
 // * @param document the document to check
 // * @param lineDelimiter the line delimiter to check for
 // */
 // private static boolean usesLineDelimiterExclusively(IDocument document, String lineDelimiter) {
 //
 // try {
 // final int lineCount= document.getNumberOfLines();
 // for (int i= 0; i < lineCount; i++) {
 // final String delimiter= document.getLineDelimiter(i);
 // if (delimiter != null && delimiter.length() > 0 && !delimiter.equals(lineDelimiter))
 // return false;
 // }
 //
 // } catch (BadLocationException e) {
 // return false;
 // }
 //
 // return true;
 // }

     /**
      * Computes and returns the key to be used to lookup the action's label in
      * its resource bundle.
      *
      * @param lineDelimiter the line delimiter
      * @param platformLineDelimiter the platform line delimiter
      * @return the key used to lookup the action's label
      */
     private static String getLabelKey(String lineDelimiter, String platformLineDelimiter) {
         if (lineDelimiter.equals(platformLineDelimiter)) {

             if (lineDelimiter.equals("\r\n")) //$NON-NLS-1$
 return "Editor.ConvertLineDelimiter.toWindows.default.label"; //$NON-NLS-1$

             if (lineDelimiter.equals("\n")) //$NON-NLS-1$
 return "Editor.ConvertLineDelimiter.toUNIX.default.label"; //$NON-NLS-1$

             if (lineDelimiter.equals("\r")) //$NON-NLS-1$
 return "Editor.ConvertLineDelimiter.toMac.default.label"; //$NON-NLS-1$

         } else {

             if (lineDelimiter.equals("\r\n")) //$NON-NLS-1$
 return "Editor.ConvertLineDelimiter.toWindows.label"; //$NON-NLS-1$

             if (lineDelimiter.equals("\n")) //$NON-NLS-1$
 return "Editor.ConvertLineDelimiter.toUNIX.label"; //$NON-NLS-1$

             if (lineDelimiter.equals("\r")) //$NON-NLS-1$
 return "Editor.ConvertLineDelimiter.toMac.label"; //$NON-NLS-1$
 }

         return null;
     }

     /*
      * @since 3.1
      */
     private static String getString(String key) {
         try {
             return EditorMessages.getBundleForConstructedKeys().getString(key);
         } catch (MissingResourceException e) {
             return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
 }
     }

     /*
      * @see IUpdate#update()
      */
     public void update() {
         super.update();
         setEnabled(canModifyEditor());
     }

 }

